package com.jusfoun.communication.dao.impl;

import com.jusfoun.communication.constant.MessageConstant;
import com.jusfoun.communication.constant.RedisKeyConstant;
import com.jusfoun.communication.dao.MessageDao;
import com.jusfoun.communication.model.Message;
import com.jusfoun.communication.util.PageInfo;
import com.jusfoun.communication.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author player six
 * @email jslcylcy@163.com
 * @create 2017-12-12 15:46
 **/
//@Component
public class MessageDaoImpl implements MessageDao {

    private static final Logger logger = LoggerFactory.getLogger(MessageDaoImpl.class);

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public Message add(Message message) {
        long id = redisUtil.incr(RedisKeyConstant.REDIS_MESSAGE_COUNT, 1);
        message.setId(id);
        //存储消息
        saveMessage(message);
        return message;
    }

    private void saveMessage(Message message) {
        redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_APPID, message.getAppId());
        redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_CODE, String.valueOf(message.getCode()));
        redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_FROM, message.getFrom());
        redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_TO, message.getTo());
        redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_TEXT, message.getText());
        redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_TIME, String.valueOf(message.getTime().getTime()));
        redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_STATUS, String.valueOf(message.getStatus()));
        redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_TYPE, String.valueOf(message.getType()));
        if (null == message.getFileList() || message.getFileList().isEmpty()) {
            redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_FILE_SIZE, String.valueOf(0));
        } else {
            redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_FILE_SIZE, String.valueOf(message.getFileList().size()));
            for (int i = 0; i < message.getFileList().size(); i++) {
                redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_FILE_SERVERURL + ":" + i, message.getFileList().get(i).getServerUrl());
                redisUtil.saveHashKey4Null(RedisKeyConstant.REDIS_MESSAGE + message.getId(), MessageConstant.REDIS_STORE_FILE_ORIGINALFILENAME + ":" + i, message.getFileList().get(i).getOriginalFileName());
            }
        }
    }

    @Override
    public Message getById(Long id) {
        String appId = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_APPID);
        if (StringUtils.isNotBlank(appId)) {
            Message message = new Message();
            String code = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_CODE);
            String time = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_TIME);
            String text = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_TEXT);
            String from = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_FROM);
            String to = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_TO);
            String status = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_STATUS);
            String type = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_TYPE);
            String fileSize = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_FILE_SIZE);
            message.setCode(Integer.valueOf(code));
            message.setText(text);
            message.setFrom(from);
            message.setTo(to);
            message.setAppId(appId);
            message.setId(id);
            if (StringUtils.isNotBlank(type)) {
                message.setType(type);
            }
            message.setStatus(StringUtils.isBlank(status) ? MessageConstant.STATUS_SENDED : Integer.valueOf(status));
            if (StringUtils.isNotBlank(time)) {
                try {
                    Date d = new Date();
                    d.setTime(Long.valueOf(time));
                    message.setTime(d);
                } catch (Exception e) {
                    logger.error("解析时间出错", e);
                }
            }

            if (StringUtils.isNotBlank(fileSize) && Integer.valueOf(fileSize) > 0) {
                message.setFileList(getFileList(id, fileSize));
            }

            return message;
        }
        return null;
    }

    private List<Message.File> getFileList(Long id, String fileSize) {
        List<Message.File> fileList = new ArrayList<>(Integer.valueOf(fileSize));
        for (int i = 0; i < Integer.valueOf(fileSize); i++) {
            String fileServerUrl = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_FILE_SERVERURL + ":" + i);
            String fileOriginalfileName = redisUtil.getHashKey(RedisKeyConstant.REDIS_MESSAGE + id, MessageConstant.REDIS_STORE_FILE_ORIGINALFILENAME + ":" + i);
            if (StringUtils.isNotBlank(fileServerUrl) && StringUtils.isNotBlank(fileOriginalfileName)) {
                fileList.add(new Message.File(fileServerUrl, fileOriginalfileName));
            }
        }
        return fileList;
    }

    @Override
    public Message update(Message message) {
        saveMessage(message);
        return message;
    }

    @Override
    public Message push4Send(Message message) {
        redisUtil.leftPush(RedisKeyConstant.REDIS_MESSAGE_NEED_PUSH, String.valueOf(message.getId()));
        return message;
    }

    @Override
    public void addUserMessageCommon(Message message) {
        //对于普通一对一消息,发送与接收方都需要保存消息
        redisUtil.zAdd(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + message.getAppId() + ":" + message.getTo() + ":" + message.getFrom(), String.valueOf(message.getId()), message.getTime().getTime());
        redisUtil.zAdd(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + message.getAppId() + ":" + message.getFrom() + ":" + message.getTo(), String.valueOf(message.getId()), message.getTime().getTime());

        //存储当前用户的所有消息记录
        redisUtil.zAdd(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + message.getAppId() + ":" + message.getTo(), String.valueOf(message.getId()), message.getTime().getTime());
        redisUtil.zAdd(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + message.getAppId() + ":" + message.getFrom(), String.valueOf(message.getId()), message.getTime().getTime());
    }

    @Override
    public void addUserMessageSystem(Message message) {
        //对于系统消息,保存
        redisUtil.zAdd(RedisKeyConstant.REDIS_MESSAGE_SYSTEM_IDLIST_PREFIX + message.getAppId() + ":" + message.getTo(), String.valueOf(message.getId()), message.getTime().getTime());
        //存储当前用户的所有消息记录
        redisUtil.zAdd(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + message.getAppId() + ":" + message.getTo(), String.valueOf(message.getId()), message.getTime().getTime());
    }

    @Override
    public List<Long> getOfflineIdList(String appId, String userName) {
        String key = RedisKeyConstant.REDIS_MESSAGE_OFFLINE_PREFIX + appId + ":" + userName;
        String value;
        List<Long> idList = new ArrayList<>();
        while ((value = redisUtil.rightPop(key)) != null) {
            if (StringUtils.isNotBlank(value)) {
                idList.add(Long.valueOf(value));
            }
        }
        return idList;
    }

    @Override
    public Long getMsgId4Send() {
        String id = redisUtil.rightPop(RedisKeyConstant.REDIS_MESSAGE_NEED_PUSH, 1, TimeUnit.MINUTES);
        if (StringUtils.isNotBlank(id)) {
            return Long.valueOf(id);
        }
        return null;
    }

    @Override
    public long listHistoryMsgCount(String appId, String to, String from) {
        return redisUtil.zSize(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + appId + ":" + to + ":" + from);
    }

    @Override
    public List<String> listHistoryMsgId(String appId, String to, String from, PageInfo pageInfo, Boolean scanIndexForward) {
        if (pageInfo.getStartRow() > 0 && pageInfo.getEndRow() >= pageInfo.getStartRow()) {
            return new ArrayList<>(redisUtil.zRangeByIdx(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + appId + ":" + to + ":" + from, pageInfo.getStartRow() - 1L, pageInfo.getEndRow() - pageInfo.getStartRow() + 1L, scanIndexForward));
        } else {
            return new ArrayList<>(redisUtil.zRangeByIdx(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + appId + ":" + to + ":" + from, 0, pageInfo.getTotal(), scanIndexForward));
        }
    }

    @Override
    public long listHistoryMsgCount(String appId, String user, long min, long max) {
        return redisUtil.zCount(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + appId + ":" + user, min, max);
    }

    @Override
    public List<String> listHistoryMsgId(String appId, String user, PageInfo pageInfo, Boolean scanIndexForward, long min, long max) {
        if (pageInfo.getStartRow() > 0 && pageInfo.getEndRow() >= pageInfo.getStartRow()) {
            return new ArrayList<>(redisUtil.zRangeByScoreAndIdx(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + appId + ":" + user, pageInfo.getStartRow() - 1L, pageInfo.getEndRow() - pageInfo.getStartRow() + 1L, scanIndexForward, min, max));
        } else {
            return new ArrayList<>(redisUtil.zRangeByScoreAndIdx(RedisKeyConstant.REDIS_MESSAGE_IDLIST_PREFIX + appId + ":" + user, 0, pageInfo.getTotal(), scanIndexForward, min, max));
        }
    }

    @Override
    public Message push4OffLine(Message message) {
        redisUtil.leftPush(RedisKeyConstant.REDIS_MESSAGE_OFFLINE_PREFIX + message.getAppId() + ":" + message.getTo(), String.valueOf(message.getId()));
        return message;
    }

    @Override
    public void dealLoginMsg(String appId, String userName) {

    }

    @Override
    public void dealLogoutMsg(String appId, String userName) {

    }
}
